package org.jsola.contract.service.impl;

import org.jsola.common.SafeKit;
import org.jsola.contract.constant.ContractConstants;
import org.jsola.contract.dao.IContractVariableDAO;
import org.jsola.contract.dto.ContractVariableAddDTO;
import org.jsola.contract.dto.ContractVariableUpdateDTO;
import org.jsola.contract.entity.ContractVariableDO;
import org.jsola.contract.entity.PersonSignatureDO;
import org.jsola.contract.query.ContractVariableQuery;
import org.jsola.contract.service.IContractVariableService;
import org.jsola.contract.vo.ContractVariableListVO;
import org.jsola.contract.vo.ContractVariableVO;
import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.orm.filter.Order;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.mapperhelper.EntityHelper;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 合同关联模板变量
 *
 * @author JanusMix
 */
@Service("contractContractVariableServiceImpl")
public class ContractVariableServiceImpl implements IContractVariableService {

    @Autowired
    private IContractVariableDAO contractVariableDAO;

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public ContractVariableVO save(ContractVariableAddDTO contractVariableAddDTO, TokenUser tokenUser) {
        // 转DO
        ContractVariableDO contractVariableDO = contractVariableAddDTO.to(ContractVariableDO.class);
        this.checkRules(contractVariableDO, tokenUser.getSiteId());
        // 保存
        contractVariableDO = save(contractVariableDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return contractVariableDO.to(ContractVariableVO.class);
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public List<ContractVariableVO> batchSave(List<ContractVariableAddDTO> contractVariableAddDTOList, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(contractVariableAddDTOList)) {
            return null;
        }
        List<ContractVariableDO> contractVariableDOList = contractVariableAddDTOList
                .parallelStream()
                .map(contractVariableAddDTO -> {
                    ContractVariableDO contractVariableDO = contractVariableAddDTO.to(ContractVariableDO.class);
                    contractVariableDO.preInsert(tokenUser.getUserId());
                    contractVariableDO.setSiteId(tokenUser.getSiteId());
                    this.checkRules(contractVariableDO, tokenUser.getSiteId());
                    return contractVariableDO;
                }).collect(Collectors.toList());
        contractVariableDAO.insertListAndSetId(contractVariableDOList);
        return contractVariableDOList
                .parallelStream()
                .map(contractVariableDO -> contractVariableDO.to(ContractVariableVO.class))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public int update(ContractVariableUpdateDTO contractVariableUpdateDTO, TokenUser tokenUser) {
        //转DO
        ContractVariableDO contractVariableDO = contractVariableUpdateDTO.to(ContractVariableDO.class);
        this.checkRules(contractVariableDO, tokenUser.getSiteId());
        //根据主键更新，只更新非null值
        return updateByIdSelective(contractVariableDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, Long... contractVariableIds) {
        return deleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) contractVariableIds);
    }


    @Override
    public ContractVariableVO selectById(Long contractVariableId, String siteId) {
        ContractVariableDO contractVariableDO = selectDOById(contractVariableId, siteId);
        if (contractVariableDO == null) {
            return null;
        }
        return contractVariableDO.to(ContractVariableVO.class);
    }

    @Override
    public List<ContractVariableListVO> select(ContractVariableQuery contractVariableQuery, String siteId) {
        List<ContractVariableDO> contractVariableDOList = selectDO(contractVariableQuery, siteId);
        if (CollectionUtils.isEmpty(contractVariableDOList)) {
            return contractVariableDOList == null ? null : new ArrayList<>();
        }
        return contractVariableDOList.stream()
                .map(contractVariableDO -> contractVariableDO.to(ContractVariableListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(ContractVariableQuery contractVariableQuery, String siteId) {
        return contractVariableDAO.findCountByQuery(contractVariableQuery, siteId);
    }

    @Override
    public Page<ContractVariableListVO> selectPage(ContractVariableQuery contractVariableQuery, String siteId) {
        //将order参数中的propertyName改为dbName
        List<Order> orders = contractVariableQuery.getOrders();
        if (!CollectionUtils.isEmpty(orders)) {
            orders.forEach(order ->
                    order.setProperty(EntityHelper.getEntityTable(ContractVariableDO.class).getPropertyMap().get(order.getProperty()).getColumn())
            );
        }
        contractVariableQuery.setOrders(orders);
        Page<ContractVariableDO> page = contractVariableDAO.findPageByQuery(contractVariableQuery, siteId);
        return page.to(ContractVariableListVO.class);
    }

    @Override
    public ContractVariableDO selectDOById(Long contractVariableId, String siteId) {
        return contractVariableDAO.findById(contractVariableId, siteId);
    }

    @Override
    public List<ContractVariableDO> selectDO(ContractVariableQuery contractVariableQuery, String siteId) {
        //将order参数中的propertyName改为dbName
        List<Order> orders = contractVariableQuery.getOrders();
        if (!CollectionUtils.isEmpty(orders)) {
            orders.forEach(order ->
                    order.setProperty(EntityHelper.getEntityTable(ContractVariableDO.class).getPropertyMap().get(order.getProperty()).getColumn())
            );
        }
        contractVariableQuery.setOrders(orders);
        return contractVariableDAO.findListByQuery(contractVariableQuery, siteId);
    }

    /**
     * 参数唯一校验
     */
    private void checkRules(ContractVariableDO contractVariableDO, String siteId) {
        Example example1 = new Example(ContractVariableDO.class);
        List<String> fieldValue1 = new ArrayList<>();
        fieldValue1.add(SafeKit.getString(contractVariableDO.getContractId()));
        example1.and().andEqualTo("contractId", contractVariableDO.getContractId());
        fieldValue1.add(SafeKit.getString(contractVariableDO.getVariableId()));
        example1.and().andEqualTo("variableId", contractVariableDO.getVariableId());
        //如果是更新，判断更新前后的唯一索引有没有产生变化
        if (contractVariableDO.getId() != null) {
            ContractVariableDO existDO = contractVariableDAO.selectOneByExample(example1);
            if (existDO != null && !existDO.getId().equals(contractVariableDO.getId())) {
                throw new ParamException("合同id 变量id [" + String.join(",", fieldValue1) + "]值重复");
            }
        } else {
            if (contractVariableDAO.selectCountByExample(example1) > 0) {
                throw new ParamException("合同id 变量id [" + String.join(",", fieldValue1) + "]值重复");
            }
        }
    }

    @Override
    @Transactional(value = ContractConstants.TX, rollbackFor = Exception.class)
    public void deleteByContractId(Long contractId, TokenUser tokenUser) {
        Example example = new Example(ContractVariableDO.class);
        example.and()
                .andEqualTo("contractId", contractId)
                .andEqualTo("siteId", tokenUser.getSiteId());
        contractVariableDAO.deleteByExample(example);
    }

    @Override
    public void deleteByContractIds(List<Long> contractIds, TokenUser tokenUser) {
        if (CollectionUtils.isEmpty(contractIds)) {
            return;
        }
        Example example = new Example(ContractVariableDO.class);
        example.and()
                .andIn("contractId", contractIds)
                .andEqualTo("siteId", tokenUser.getSiteId());
        contractVariableDAO.deleteByExample(example);
    }

}




